package com.xayy.health.ds.service.impl;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.Method;
import cn.kawins.base.utils.BeanUtil;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.base.utils.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xayy.health.core.config.param.YcParam;
import com.xayy.health.core.constant.HealthManagerConstant;
import com.xayy.health.core.exception.HealthException;
import com.xayy.health.ds.model.DsTaskInfo;
import com.xayy.health.ds.model.DsTaskParamInfo;
import com.xayy.health.ds.model.DsTelemetryData;
import com.xayy.health.ds.service.*;
import com.xayy.health.mgt.model.TelemetryData;
import com.xayy.health.mgt.model.dto.DataFeatureDto;
import com.xayy.health.mgt.model.dto.TelemetryDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
@Slf4j
public class DsDiagnoseServiceImpl implements DsDiagnoseService {
    @Autowired
    DsTaskParamInfoService dsTaskParamInfoService;
    @Autowired
    DsTaskInfoService dsTaskInfoService;
    @Autowired
    private YcParam ycParam;
    @Autowired
    DsTelemetryDataService dsTelemetryDataService;
    @Autowired
    DsSelectTelemetryDataService dsSelectTelemetryDataService;

    /**
     * 获取遥测参数
     *
     * @param telemetryDto 遥测入参
     * @return Map<String, List < TelemetryData>>
     */
    @Override
    public Map<String, List<DsTelemetryData>> selectTelemetryData(TelemetryDto telemetryDto) {
        Map<String, List<DsTelemetryData>> result = new HashMap<>(1);
        if (BeanUtil.isEmpty(telemetryDto) || telemetryDto.getStartTime() == null || telemetryDto.getEndTime() == null) {
            return result;
        }
        String[] paramCodes = telemetryDto.getParamCodes();
        for (String paramCode : paramCodes) {
            List<DsTelemetryData> telemetryDataList = new ArrayList<>();
            // 获取数据有预处理结果则用没有去原始数据
            DsTaskParamInfo taskParamInfo = new DsTaskParamInfo();
            List<DsTaskParamInfo> taskParamInfoList = dsTaskParamInfoService.selectTList(DsTaskParamInfo.builder().satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).status(1).build());
            if (null!=taskParamInfoList && taskParamInfoList.size()>0){
                taskParamInfo = taskParamInfoList.get(0);
            }

            if (BeanUtil.isNotEmpty(taskParamInfo)) {
                DsTaskInfo taskInfo = dsTaskInfoService.selectTById(taskParamInfo.getTaskId());
                if (null != taskInfo) {
                    telemetryDataList = getTelemetry(telemetryDto, taskInfo, paramCode);
                }
            } else {
                DataFeatureDto dataFeatureDto = DataFeatureDto.builder().startTime(telemetryDto.getStartTime()).endTime(telemetryDto.getEndTime()).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                telemetryDataList = getYcList(dataFeatureDto);
            }
            result.put(paramCode, telemetryDataList);
        }
        return result;
    }

    /**
     * 事后诊断和趋势预测所用入参数据获取
     *
     * @param telemetryDto 入参
     * @param taskInfo     任务时间
     * @param paramCode    参数
     * @return 结果
     */
    private List<DsTelemetryData> getTelemetry(TelemetryDto telemetryDto, DsTaskInfo taskInfo, String paramCode) {
        List<DsTelemetryData> telemetryDataList = new ArrayList<>();
        Date startTimeTelemetry = telemetryDto.getStartTime();
        Date endTimeTelemetry = telemetryDto.getEndTime();
        Date startTimeTask = taskInfo.getStartTime();
        Date endTimeTask = taskInfo.getEndTime();

        // 开始时间小于任务开始时间
        if (startTimeTelemetry.getTime() < startTimeTask.getTime()) {
            // 结束时间小于任务开始时间,全部查询遥测
            if (endTimeTelemetry.getTime() <= startTimeTask.getTime()) {
                DataFeatureDto dataFeatureDto = DataFeatureDto.builder().startTime(startTimeTelemetry).endTime(endTimeTelemetry).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                telemetryDataList = getYcList(dataFeatureDto);
                return telemetryDataList;

            } else if (endTimeTelemetry.getTime() <= endTimeTask.getTime()) {
                // 结束时间小于等于任务结束时间,开始时间到任务开始时间查询遥测，任务开始时间到结束时间查处理数据
                DataFeatureDto dataFeatureDto = DataFeatureDto.builder().startTime(startTimeTelemetry).endTime(startTimeTask).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                List<DsTelemetryData> telemetryDataList1 = getYcList(dataFeatureDto);

                DataFeatureDto dataFeatureDto1 = DataFeatureDto.builder().startTime(startTimeTask).endTime(endTimeTelemetry).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).parentTaskId(taskInfo.getId()).build();
                List<DsTelemetryData> telemetryDataList2 = dsTelemetryDataService.getPhList(dataFeatureDto1);

                telemetryDataList.addAll(telemetryDataList1);
                telemetryDataList.addAll(telemetryDataList2);
                return telemetryDataList;
            } else {
                // 结束时间大于任务结束时间，开始时间到任务开始时间和任务结束时间到结束时间查遥测，任务时间段查处理数据
                DataFeatureDto dataFeatureDto1 = DataFeatureDto.builder().startTime(startTimeTelemetry).endTime(startTimeTask).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                List<DsTelemetryData> telemetryDataList1 = getYcList(dataFeatureDto1);

                DataFeatureDto dataFeatureDto2 = DataFeatureDto.builder().startTime(endTimeTask).endTime(endTimeTelemetry).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).parentTaskId(taskInfo.getId()).build();
                List<DsTelemetryData> telemetryDataList2 = dsTelemetryDataService.getPhList(dataFeatureDto2);

                DataFeatureDto dataFeatureDto3 = DataFeatureDto.builder().startTime(startTimeTask).endTime(endTimeTask).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                List<DsTelemetryData> telemetryDataList3 = getYcList(dataFeatureDto3);

                telemetryDataList.addAll(telemetryDataList1);
                telemetryDataList.addAll(telemetryDataList3);
                telemetryDataList.addAll(telemetryDataList2);
                return telemetryDataList;
            }

        } else { // 开始时间大于等于任务开始时间
            if (startTimeTelemetry.getTime() > endTimeTask.getTime()) {
                // 开始时间大于任务结束时间，查询遥测
                DataFeatureDto dataFeatureDto = DataFeatureDto.builder().startTime(startTimeTelemetry).endTime(endTimeTelemetry).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                telemetryDataList = getYcList(dataFeatureDto);
                return telemetryDataList;
            } else if (endTimeTelemetry.getTime() <= endTimeTask.getTime()) {
                // 结束时间是否小于等于任务结束时间，查询处理后的数据
                DataFeatureDto dataFeatureDto = DataFeatureDto.builder().startTime(startTimeTelemetry).endTime(endTimeTelemetry).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).parentTaskId(taskInfo.getId()).build();
                telemetryDataList = dsTelemetryDataService.getPhList(dataFeatureDto);
                return telemetryDataList;
            } else {
                // 开始时间到任务结束时间查处理数据，任务结束时间到结束时间查遥测
                DataFeatureDto dataFeatureDto1 = DataFeatureDto.builder().startTime(startTimeTelemetry).endTime(endTimeTask).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).parentTaskId(taskInfo.getId()).build();
                List<DsTelemetryData> telemetryDataList1 = dsTelemetryDataService.getPhList(dataFeatureDto1);

                DataFeatureDto dataFeatureDto2 = DataFeatureDto.builder().startTime(endTimeTask).endTime(endTimeTelemetry).satelliteCode(telemetryDto.getSatelliteCode()).paramCode(paramCode).build();
                List<DsTelemetryData> telemetryDataList2 = getYcList(dataFeatureDto2);
                telemetryDataList.addAll(telemetryDataList1);
                telemetryDataList.addAll(telemetryDataList2);
                return telemetryDataList;
            }
        }

    }

    /**
     * 获取遥测信息
     *
     * @param dataFeatureDto 入参信息
     * @return 结果日志
     */
    @Override
    public List<DsTelemetryData> getYcList(DataFeatureDto dataFeatureDto) {
        if (Boolean.TRUE.equals(ycParam.getYcApiOrDb())) {
            return getYcListByApi(dataFeatureDto);
        } else {
            List<DsTelemetryData> ycList = dsTelemetryDataService.getYcList(dataFeatureDto);

            if (!CollectionUtils.isEmpty(ycList)) {
                for (DsTelemetryData telemetryData : ycList) {
                    if (StringUtils.isEmpty(telemetryData.getValue())) {
                        telemetryData.setValue(null);
                    }
                }
            }
            return ycList;
        }
    }

    /**
     * 从api获取遥测数据
     *
     * @param dataFeatureDto 入参
     * @return List<TelemetryData>
     */
    private List<DsTelemetryData> getYcListByApi(DataFeatureDto dataFeatureDto) {
        JSONObject parms = new JSONObject();
        if (dataFeatureDto.getStartTime() != null) {
            long startTimeStamp = dataFeatureDto.getStartTime().getTime();
            parms.put("timeStart", startTimeStamp);
        }
        if (dataFeatureDto.getEndTime() != null) {
            long endTimeStamp = dataFeatureDto.getEndTime().getTime();
            parms.put("timeEnd", endTimeStamp);
        }
        parms.put("param", new ArrayList<>());
        List<String> column = new ArrayList<>();
        column.add("time");
        column.add(dataFeatureDto.getParamCode());
        parms.put("column", column);
        parms.put("timeField", "time");
        Integer timeInterval = dataFeatureDto.getTimeInterval();
        if (timeInterval != null && timeInterval.compareTo(0) > 0) {
            parms.put("jumpPoint", timeInterval+"s");
            column.remove(1);
            column.add(dataFeatureDto.getParamCode());
        }
        parms.put("businessKey", dataFeatureDto.getSatelliteCode());
        log.info("****************************调用遥测入参****************************");
        log.info(parms.toString());
        log.info("********************************************************");
        // 1通信2中继
        List<DsTelemetryData> ycList = new ArrayList<>();
        log.info("****************************开始遥测调用****************************");
        HttpResponse getResponse = HttpUtil.createRequest(Method.POST, ycParam.getYcApi()).body(parms.toString()).timeout(600000).execute();
        if (getResponse.getStatus() != HttpStatus.HTTP_OK) {
            throw new RuntimeException("调用查询遥测接口异常");
        }
        log.info("****************************遥测调用完成****************************");
        JSONArray ycVos = JSON.parseObject(getResponse.body()).getJSONArray("data");
        long timeFormatStart = System.currentTimeMillis();
        log.info("遥测时间格式处理开始时间：" + timeFormatStart);

        //判断遥测数据是否全部为空
        if (CollUtil.isNotEmpty(ycVos)) {
            ycVos.forEach(ycData -> {
                JSONObject item = JSONObject.parseObject(JSON.toJSONString(ycData), JSONObject.class);

                String time = item.getString("time");
                String value = item.getString(dataFeatureDto.getParamCode());

                DsTelemetryData telemetryData = new DsTelemetryData();
                telemetryData.setSateCode(dataFeatureDto.getSatelliteCode());
                telemetryData.setParamCode(dataFeatureDto.getParamCode());
                //log.info("遥测时间原始格式：" + time);
                if (time.length() > HealthManagerConstant.TIME_TWENTY_THREE) {
                    String millsTime = time.substring(0, 23);
                    String timeStr = millsTime.replace("T", " ");
                    telemetryData.setTime(timeStr);
                    //log.info("遥测时间处理之后的格式：" + timeStr);
                } else {
                    telemetryData.setTime(time);
                }
                if(StringUtils.isEmpty(value)){
                    value = null;
                }
                telemetryData.setValue(value);
                ycList.add(telemetryData);
            });
        } else {
            //TODO: 业务处理信息应返回正常的对象,而不是抛出异常
            throw new HealthException("参数" + dataFeatureDto.getParamCode() + "遥测数据为空");
        }
        long timeFormatEnd = System.currentTimeMillis();
        log.info("遥测时间格式处理完成时间：" + timeFormatEnd);
        log.info("遥测时间格式处理总耗时={}",timeFormatEnd-timeFormatStart);
        return ycList;
    }

    /**
     * 查询使用后的测遥数据(自动运行或者模型训练使用后的)
     * @param telemetryDto 遥测入参
     * @return Map<String, List < TelemetryData>>
     */
    @Override
    public Map<String, List<DsTelemetryData>> selectUsedTelemetryData(String tableName, TelemetryDto telemetryDto) {
        Map<String, List<DsTelemetryData>> result = new HashMap<>(1);
        String[] paramCodes = telemetryDto.getParamCodes();
        for (String paramCode : paramCodes) {
            /*查询保存后的遥测数据*/
            telemetryDto.setParamCode(paramCode);
            List<DsTelemetryData> ycList = null;
            try {
                ycList = dsSelectTelemetryDataService.selectTelemetryListData(tableName,telemetryDto);
            } catch (Exception e) {
                log.error("selectUsedTelemetryData errors...tableName={},telemetryDto={}",tableName,telemetryDto,e);
            }
            result.put(paramCode, ycList);
        }
        return result;
    }
}
